package wiki.zimo.servlet.reception;

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.config.AlipayConfig;
import wiki.zimo.constant.Constant;
import wiki.zimo.dao.OrderDao;
import wiki.zimo.dao.OrderItemDao;
import wiki.zimo.dao.ProductDao;
import wiki.zimo.domain.*;
import wiki.zimo.servlet.BaseServlet;
import wiki.zimo.utils.DataSourceUtils;
import wiki.zimo.utils.UUIDUtils;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * @version v1.0
 * @auther: 子墨
 * @datetime: 2018/11/5 11:09
 * @description: 处理订单的Servlet
 */
@WebServlet(value = "/order")
public class OrderServlet extends BaseServlet {

    private OrderDao orderDao = new OrderDao();
    private OrderItemDao orderItemDao = new OrderItemDao();
    private ProductDao productDao = new ProductDao();

    /**
     * @auther: 子墨
     * @date: 2018/11/5 11:20
     * @describe: 保存订单接口
     * @param: [request, response]
     * @return: java.lang.String
     * @version v1.0
     */
    public String saveOrder(HttpServletRequest request, HttpServletResponse response) {

        HttpSession session = request.getSession();

        // 获取当前登录用户
        User user = (User) session.getAttribute(Constant.USER_LOG_ON);
        if (user == null) {
            // 用户为空
            request.setAttribute(Constant.MSG, "请登录后下单");
            return Constant.URL_USER_LOGIN;
        }

        // 获取购物车
        Cart cart = (Cart) session.getAttribute(Constant.CART);
        if (cart == null || cart.getCartItems().size() <= 0) {
            // 购物车为空
            return Constant.URL_CART;
        }

        Order order = getOrder(user, cart);
        List<Orderitem> orderitems = getOrderItems(order, cart);
        order.setOrderItems(orderitems);

        // 保存到页面上展示,注意这里要保存到session中
        session.setAttribute(Constant.ORDER, order);

        // 保存订单到数据库
        try {
            // 开启事务
            DataSourceUtils.beginTransaction();
            orderDao.insert(order);
            for (Orderitem item : orderitems) {
                orderItemDao.insert(item);
            }
            // 提交事务
            DataSourceUtils.commitTransaction();

            // 提交订单之后清空购物车
            cart.clearCart();

        } catch (Exception e) {
            e.printStackTrace();
            // 回滚事务
            DataSourceUtils.rollbackAndClose();
        }

        // 重定向到确认订单支付页面
        return Constant.REDIRECT + Constant.URL_PAY_ORDER;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/8 13:10
     * @describe: 保存订单收货地址
     * @param: [request, response]
     * @return: java.lang.String
     * @version v1.0
     */
    public String saveAddress(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        Order order = (Order) session.getAttribute(Constant.ORDER);
        if (order == null) {
            return null;
        }
        String name = request.getParameter("name");
        String telephone = request.getParameter("telephone");
        String address = request.getParameter("address");

        System.out.println(name + "," + address);
        order.setName(name);
        order.setTelephone(telephone);
        order.setAddress(address);
        orderDao.update(order);

        // 更新order信息
        session.setAttribute(Constant.ORDER, order);

        // 重定向到确认订单支付页面
        return Constant.REDIRECT + Constant.URL_PAY_ORDER;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/8 12:54
     * @describe: 支付订单 -> 调用支付宝支付接口
     * @param: [request, response]
     * @return: java.lang.String
     * @version v1.0
     */
    public String payOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String oid = request.getParameter("oid");
        Order order = getOrder(oid);

        // 保存到session
        HttpSession session = request.getSession();
        session.setAttribute(Constant.ORDER, order);

        if (order.getAddress() == null) {
            // 没设置收货地址
            return Constant.REDIRECT + Constant.URL_PAY_ORDER;
        }

        // 调用支付宝支付接口
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        // 设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        // 商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = order.getOid();
        // 付款金额，必填
        String total_amount = order.getTotal() + "";
        // 订单名称，必填
        String subject = "子墨商城订单";

        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"total_amount\":\"" + total_amount + "\","
                + "\"subject\":\"" + subject + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        // 获得请求结果
        String result = alipayClient.pageExecute(alipayRequest).getBody();

        response.setContentType("text/html;charset=" + AlipayConfig.charset);
        response.getWriter().write(result);
        response.getWriter().flush();
        response.getWriter().close();
        return null;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/6 23:30
     * @describe: 我的订单列表页
     * @param: [request, response]
     * @return: java.lang.String
     * @version v1.0
     */
    public String myOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();

        // 获取当前登录用户
        User user = (User) session.getAttribute(Constant.USER_LOG_ON);
        if (user == null) {
            // 用户为空
            request.setAttribute(Constant.MSG, "请登录后查看我的订单");
            return Constant.URL_USER_LOGIN;
        }

        // 得到该用户的所有订单集
        List<Order> orders = orderDao.findOrdersByUid(user.getUid());
        for (Order o : orders) {
            // 得到订单集下面的订单项集
            List<Orderitem> orderitems = orderItemDao.findOrderitemsByOid(o.getOid());
            // 得到订单项集中的product
            for (Orderitem item : orderitems) {
                Product product = productDao.findOneById(item.getPid());
                item.setProduct(product);
            }
            // 设置到订单集中
            o.setOrderItems(orderitems);
        }

        System.out.println(orders);
        request.setAttribute(Constant.ORDERS, orders);
        return Constant.URL_MY_ORDER;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/7 13:42
     * @describe: 删除订单接口
     * @param: [request, response]
     * @return: java.lang.String
     * @version v1.0
     */
    public String deleteOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String oid = request.getParameter("oid");
        Order order = orderDao.findOneById(oid);
        if (order != null && order.getState() == Constant.ORDER_NOT_PAY) {
            orderDao.delete(order);
            return myOrder(request, response);
        }
        request.setAttribute(Constant.MSG, "不允许删除此类订单");
        return myOrder(request, response);
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/10 10:00
     * @describe: 确认收货接口
     * @param: [request, response]
     * @return: java.lang.String
     * @version v1.0
     */
    public String finishOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String oid = request.getParameter("oid");
        Order order = orderDao.findOneById(oid);
        if (order != null && order.getState() != Constant.ORDER_NOT_PAY) {
            order.setState(Constant.ORDER_FINISH);
            orderDao.update(order);
            return myOrder(request, response);
        }
        request.setAttribute(Constant.MSG, "不允许确认收货此类订单");
        return myOrder(request, response);
    }


    /**
     * @auther: 子墨
     * @date: 2018/11/6 16:59
     * @describe: 从购物车生成订单
     * @param: [user, cart]
     * @return: wiki.zimo.domain.Order
     * @version v1.0
     */
    private Order getOrder(User user, Cart cart) {
        // 封装Order对象
        Order order = new Order();
        order.setOid(UUIDUtils.getRandomId());
        order.setUid(user.getUid());
        order.setOrdertime(new Timestamp(System.currentTimeMillis()));
        order.setTotal(cart.getTotal());
        // 订单初始状态——未付款
        order.setState(Constant.ORDER_NOT_PAY);
        return order;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/8 14:01
     * @describe: 得到待支付的订单
     * @param: [oid]
     * @return: wiki.zimo.domain.Order
     * @version v1.0
     */
    private Order getOrder(String oid) throws Exception {
        // 获取订单
        Order order = orderDao.findOneById(oid);
        List<Orderitem> orderitems = orderItemDao.findOrderitemsByOid(order.getOid());
        for (Orderitem item : orderitems) {
            Product product = productDao.findOneById(item.getPid());
            item.setProduct(product);
        }
        order.setOrderItems(orderitems);
        return order;
    }

    /**
     * @auther: 子墨
     * @date: 2018/11/6 17:01
     * @describe: 生成某个订单的订单项
     * @param: [order, cart]
     * @return: java.util.List<wiki.zimo.domain.Orderitem>
     * @version v1.0
     */
    private List<Orderitem> getOrderItems(Order order, Cart cart) {
        // 封装购物项集合
        List<Orderitem> orderitems = new ArrayList<>();
        for (CartItem item : cart.getCartItems()) {
            Orderitem orderitem = new Orderitem();
            orderitem.setItemid(UUIDUtils.getRandomId());
            orderitem.setOid(order.getOid());
            orderitem.setPid(item.getProduct().getPid());
            // 保存一个商品信息到orderitem中，方便展示图片
            orderitem.setProduct(item.getProduct());
            orderitem.setCount(item.getCount());
            orderitem.setSubTotal(item.getSubTotal());
            orderitems.add(orderitem);
        }
        return orderitems;
    }
}
